package com.shigen.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shigen.demo.Enum.HttpStatusCode;
import com.shigen.demo.config.ConfigProperty;
import com.shigen.demo.entity.BaseUserFile;
import com.shigen.demo.entity.UserInfo;
import com.shigen.demo.entity.req.BaseUserFileReq.QueryByFolder;
import com.shigen.demo.entity.req.FileFolderReq.CreateFolderReq;
import com.shigen.demo.entity.vo.FileNodeVo;
import com.shigen.demo.exception.BusinessException;
import com.shigen.demo.mapper.BaseUserFileMapper;
import com.shigen.demo.service.IBaseUserFileService;
import com.shigen.demo.service.UserService;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class BaseUserFileServiceImpl extends ServiceImpl<BaseUserFileMapper, BaseUserFile> implements IBaseUserFileService {

  @Resource
  private ConfigProperty configProperty;
  @Resource
  private UserService userService;

  @Override
  public List<FileNodeVo> listWithTree() {
    List<BaseUserFile> baseUserFiles = getBaseUserFilesByUserId(userService.getUserInfo().getUserId());
    if (CollectionUtil.isEmpty(baseUserFiles)) {
      return null;
    } else {
      // BaseUserFile -> FileNodeVo
      List<FileNodeVo> fileNodeVos = baseUserFiles.stream().map(baseUserFile -> {
        FileNodeVo fileNodeVo = new FileNodeVo();
        BeanUtil.copyProperties(baseUserFile, fileNodeVo);
        return fileNodeVo;
      }).collect(Collectors.toList());

      // 获取所有的一级目录
      List<FileNodeVo> list = fileNodeVos.stream().filter(fileNodeVo -> fileNodeVo.getParentId().equals("0")).map(fileNodeVo -> {
        fileNodeVo.setChildren(getChildrenData(fileNodeVo, fileNodeVos));
        return fileNodeVo;
      }).collect(Collectors.toList());
      return list;
    }
  }

  // 获取下级目录
  private List<FileNodeVo> getChildrenData(FileNodeVo root, List<FileNodeVo> fileNodeVos) {
    List<FileNodeVo> children = fileNodeVos.stream().filter(fileNodeVo ->
        fileNodeVo.getParentId().equals(root.getUnionId())
    ).map(fileNodeVo -> {
      fileNodeVo.setChildren(getChildrenData(fileNodeVo, fileNodeVos));
      return fileNodeVo;
    }).collect(Collectors.toList());
    return children;
  }

  // 获得创建人所有的文件
  private List<BaseUserFile> getBaseUserFilesByUserId(Integer userId) {
    return lambdaQuery().eq(userId != null, BaseUserFile::getUploadUserId, userId).eq(BaseUserFile::getIsDel, false).list();
  }

  @Override
  public String uploadFile(MultipartFile file, String savePath) {
    if (file.isEmpty()) {
      throw new BusinessException("上传的文件为空！");
    }
    String fileName = File.separator + IdUtil.simpleUUID() + "." + FileNameUtil.extName(file.getOriginalFilename());
    // 重命名文件
    File newFile = new File(savePath, fileName);
    // 存储路径不存在就创建路径
    if (!newFile.getParentFile().exists()) {
      newFile.getParentFile().mkdirs();
    }
    try {
      file.transferTo(newFile);
      return fileName;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public int uploadFiles(MultipartFile[] files, String parentId) {
    UserInfo userInfo = userService.getUserInfo();

    ArrayList<BaseUserFile> baseUserFiles = new ArrayList<>();
    for (int i = 0; i < files.length; i++) {
      String savePath = this.uploadFile(files[i], configProperty.getSavePath());
      if (savePath != null) {
        BaseUserFile baseUserFile = new BaseUserFile().setUnionId(IdUtil.simpleUUID())
            .setParentId(parentId)
            .setUploadUserId(Long.valueOf(userInfo.getUserId()))
            .setName(files[i].getOriginalFilename())
            .setSize(files[i].getSize())
            .setUploadUserName(userInfo.getUserName())
            .setType(FileUtil.getSuffix(files[i].getOriginalFilename()))
            .setUrl(savePath)
            .setNote("")
            .setIsDel(false)
            .setIsPublic(false)
            .setCreateTime(new Date())
            .setUpdateTime(new Date());
        baseUserFiles.add(baseUserFile);
      }
    }
    return this.getBaseMapper().insertBatch(baseUserFiles);
  }

  @Override
  public IPage<BaseUserFile> getFolderFilesByPage(QueryByFolder queryByFolder) {
    Page<BaseUserFile> page = new Page<>(queryByFolder.getPagenum(), queryByFolder.getPagesize());
    String folderId = queryByFolder.getFolderId();
    return lambdaQuery().eq(folderId != null, BaseUserFile::getParentId, folderId).page(page);
  }

  @Override
  public List<BaseUserFile> getFolderFiles(String folderId) {
    return lambdaQuery().eq(folderId != null, BaseUserFile::getParentId, folderId).eq(BaseUserFile::getIsDel, false).list();
  }

  @Override
  public BaseUserFile getFileDetail(Long id) {
    return getBaseMapper().selectById(id);
  }

  @Override
  public boolean delBatchByUnionId(ArrayList<String> unionIds) {
    return lambdaUpdate().set(BaseUserFile::getIsDel, true).in(BaseUserFile::getUnionId, unionIds).update();
  }

  @Override
  public int reNameFile(Long id, String newName) {
    boolean update = lambdaUpdate().set(StrUtil.isNotEmpty(newName), BaseUserFile::getName, newName).eq(BaseUserFile::getId, id).update();
    return update ? 1 : 0;
  }

  @Override
  public String findByUnionId(String unionId) {
    String baseUrl = "http://81.68.145.94/imgs/";
    BaseUserFile baseUserFile = lambdaQuery().eq(StrUtil.isNotEmpty(unionId), BaseUserFile::getUnionId, unionId).eq(BaseUserFile::getIsDel, false).one();
    if (baseUserFile != null && baseUserFile.getUrl() != null) {
      return baseUrl + baseUserFile.getUrl();
    }
    return null;
  }

  @Override
  public FileNodeVo createFolder(CreateFolderReq createFolderReq) {
    UserInfo userInfo = userService.getUserInfo();

    BaseUserFile baseUserFile = new BaseUserFile().setParentId(createFolderReq.getParentId())
        .setName(createFolderReq.getName())
        .setNote(createFolderReq.getNote())
        .setIsPublic(createFolderReq.getIsPublic())
        .setUnionId(IdUtil.simpleUUID())
        .setUploadUserId(Long.valueOf(userInfo.getUserId()))
        .setUploadUserName(userInfo.getUserName());
    int insert = getBaseMapper().insert(baseUserFile);
    if (insert > 0) {
      FileNodeVo fileNodeVo = new FileNodeVo();
      BeanUtil.copyProperties(baseUserFile, fileNodeVo);
      return fileNodeVo;
    }
    return null;
  }

  @Override
  public boolean move(String unionId, String parentId) {
    if (StrUtil.isBlank(unionId) || StrUtil.isBlank(parentId)) {
      throw new BusinessException(HttpStatusCode.BAD_REQUEST);
    }
    return lambdaUpdate().set(BaseUserFile::getParentId, parentId).eq(BaseUserFile::getUnionId, unionId).update();
  }
}
